package com.example.java_doc_searcher.searcher;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.ansj.domain.Term;
import org.ansj.splitWord.analysis.ToAnalysis;
import org.omg.CORBA.CODESET_INCOMPATIBLE;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Index {
    private static String INDEX_PATH=null;
    static {
        if(Config.isOnline){
            INDEX_PATH="/root/searcher/";
        }else {
            INDEX_PATH="E:\\doc_searcher_index2\\";
        }
    }
    private ObjectMapper objectMapper=new ObjectMapper();
    private ArrayList<DocInfo> forwardIndex=new ArrayList<>();
    private HashMap<String,ArrayList<Weight>> invertedIndex=new HashMap<>();
    private Object locker1=new Object();
    private Object locker2=new Object();
    public DocInfo getDocInfo(int docId){

        return forwardIndex.get(docId);
    }
    public List<Weight> getInverted(String term){

        return invertedIndex.get(term);
    }
    public void addDoc(String title,String url,String content){
        DocInfo docInfo=buildForward(title,url,content);
        buildInverted(docInfo);
    }

    private void buildInverted(DocInfo docInfo) {
        class WordCnt{
            public int titleCount;
            public int contentCount;
        }
        HashMap<String,WordCnt> wordCntHashMap=new HashMap<>();
        List<Term> terms= ToAnalysis.parse(docInfo.getTitle()).getTerms();
        for(Term term:terms){
            String word=term.getName();
            WordCnt wordCnt=wordCntHashMap.get(word);
            if(wordCnt==null){
                WordCnt newWordCnt=new WordCnt();
                newWordCnt.titleCount=1;
                newWordCnt.contentCount=0;
                wordCntHashMap.put(word,newWordCnt);
            }else{
                wordCnt.titleCount+=1;
            }
        }
        terms= ToAnalysis.parse(docInfo.getContent()).getTerms();
        for(Term term:terms){
            String word=term.getName();
            WordCnt wordCnt=wordCntHashMap.get(word);
            if(wordCnt==null){
                WordCnt newWordCnt=new WordCnt();
                newWordCnt.titleCount=0;
                newWordCnt.contentCount=1;
                wordCntHashMap.put(word,newWordCnt);
            }else{
                wordCnt.contentCount+=1;
            }
        }
        for(Map.Entry<String,WordCnt> entry:wordCntHashMap.entrySet()){

            synchronized (locker2){
                List<Weight> invertedList=invertedIndex.get(entry.getKey());
                if(invertedList==null){
                    ArrayList<Weight> newInvertedList=new ArrayList<>();
                    Weight weight=new Weight();
                    weight.setDocId(docInfo.getDocId());
                    weight.setWeight(entry.getValue().titleCount*10+entry.getValue().contentCount);
                    newInvertedList.add(weight);
                    invertedIndex.put(entry.getKey(),newInvertedList);
                }else{
                    Weight weight=new Weight();
                    weight.setDocId(docInfo.getDocId());
                    weight.setWeight(entry.getValue().titleCount*10+entry.getValue().contentCount);
                    invertedList.add(weight);
                }
            }
        }
    }

    private DocInfo buildForward(String title, String url, String content) {
        DocInfo docInfo=new DocInfo();
        docInfo.setTitle(title);
        docInfo.setUrl(url);
        docInfo.setContent(content);
        synchronized (locker1){
            docInfo.setDocId(forwardIndex.size());
            forwardIndex.add(docInfo);
        }
        return docInfo;
    }

    public void save(){
        long beg=System.currentTimeMillis();
        System.out.println("保存索引开始");
        File indexPathFile =new File(INDEX_PATH);
        if(!indexPathFile.exists()){
            indexPathFile.mkdirs();
        }
        File forwardIndexFile=new File(INDEX_PATH+"forward.txt");
        File invertedIndexFile=new File(INDEX_PATH+"inverted.txt");
        try{
            objectMapper.writeValue(forwardIndexFile,forwardIndex);
            objectMapper.writeValue(invertedIndexFile,invertedIndex);
        }catch(IOException e){
            e.printStackTrace();
        }
        long end=System.currentTimeMillis();
        System.out.println("保存索引结束,消耗时间: "+(end-beg)+"ms");

    }
    public void load(){
        long beg=System.currentTimeMillis();
        System.out.println("加载索引开始");
        File forwardIndexFile=new File(INDEX_PATH+"forward.txt");
        File invertedIndexFile=new File(INDEX_PATH+"inverted.txt");
        try{
            forwardIndex=objectMapper.readValue(forwardIndexFile, new TypeReference<ArrayList<DocInfo>>() {});
            invertedIndex=objectMapper.readValue(invertedIndexFile, new TypeReference<HashMap<String, ArrayList<Weight>>>() {});

        }catch(IOException e){
            e.printStackTrace();
        }
        long end=System.currentTimeMillis();
        System.out.println("加载索引结束,消耗时间: "+(end-beg)+"ms");
    }
    public static void main(String[] args) {
        Index index=new Index();
        index.load();
        System.out.println("索引加载完成");
    }
}
